package com.yxsk.relay.job.admin.config;

import com.yxsk.relay.job.admin.config.properties.StewardTokenConfig;
import com.yxsk.relay.job.admin.config.registry.EnableRelayJobSteward;
import com.yxsk.relay.job.admin.config.registry.security.ApplicationChecker;
import com.yxsk.relay.job.admin.config.registry.security.SpecificIpSecurityChecker;
import com.yxsk.relay.job.admin.config.registry.security.TokenSecurityChecker;
import com.yxsk.relay.job.admin.core.executor.quartz.QuartzAsyncRemoteJobExecutor;
import com.yxsk.relay.job.admin.data.service.JobAppsService;
import com.yxsk.relay.job.component.admin.monitor.AsyncJobStatusMonitor;
import com.yxsk.relay.job.component.admin.registry.Steward;
import com.yxsk.relay.job.component.admin.registry.security.SecurityChecker;
import com.yxsk.relay.job.component.admin.utils.SpringBeanUtils;
import com.yxsk.relay.job.component.common.net.handler.convert.CompressAbleMessageConvert;
import com.yxsk.relay.job.component.common.net.serialization.JsonMessageEntitySerializer;
import com.yxsk.relay.job.component.common.protocol.caller.DefaultHttpClientFactory;
import com.yxsk.relay.job.component.common.protocol.caller.HttpClientFactory;
import com.yxsk.relay.job.component.common.protocol.caller.HttpRestfulRemoteCaller;
import com.yxsk.relay.job.component.common.protocol.caller.RemoteCaller;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * @Author 11376
 * @CreaTime 2019/6/19 19:27
 * @Description
 */
@Configuration
// 启用服务注册
@EnableRelayJobSteward
public class RelayJobAdminConfig implements BeanPostProcessor {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public RemoteCaller remoteCaller() {
        return HttpRestfulRemoteCaller.builder()
                .httpClientFactory(httpClientFactory())
                .messageConvert(new CompressAbleMessageConvert())
                .serializer(new JsonMessageEntitySerializer())
                .build();
    }

    @Bean
    public HttpClientFactory httpClientFactory() {
        return new DefaultHttpClientFactory();
    }

    /**
     * @param
     * @Author 11376
     * @Description 异步任务监控器
     * @CreateTime 2019/6/19 19:30
     * @Return
     */
    @Bean(initMethod = "start", destroyMethod = "stop")
    public AsyncJobStatusMonitor jobStatusMonitor() {
        return new QuartzAsyncRemoteJobExecutor.QuartzAsyncJobMonitor(remoteCaller());
    }

    /**
     * @param
     * @Author 11376
     * @Description 服务注册器授权 token
     * @CreateTime 2019/7/2 10:23
     * @Return
     */
    @Bean
    public StewardTokenConfig tokenConfig() {
        return new StewardTokenConfig();
    }

    /**
     * @param appsService
     * @Author 11376
     * @Description 服务注册器安全检查列表
     * @CreateTime 2019/7/2 10:23
     * @Return
     */
    @Bean
    public List<SecurityChecker> securityCheckers(JobAppsService appsService) {
        List<SecurityChecker> checkers = new LinkedList<>();
        checkers.add(new ApplicationChecker(appsService));
        checkers.add(new TokenSecurityChecker(Arrays.asList(tokenConfig().getToken()), appsService));
        checkers.add(new SpecificIpSecurityChecker(defaultSpecificIpGetter(appsService), appsService));
        return checkers;
    }

    /**
     * @param appsService
     * @Author 11376
     * @Description IP 授权检查 IP 列表 Getter
     * @CreateTime 2019/7/2 10:24
     * @Return
     */
    @Bean
    public SpecificIpSecurityChecker.DefaultSpecificIpGetter defaultSpecificIpGetter(JobAppsService appsService) {
        return new SpecificIpSecurityChecker.DefaultSpecificIpGetter(appsService);
    }

    /**
     * @param bean
     * @param beanName
     * @Author 11376
     * @Description 为服务注册器注入安全检查
     * @CreateTime 2019/7/2 9:55
     * @Return
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Steward) {
            Steward steward = (Steward) bean;
            // 添加授权
            List<SecurityChecker> checkers = SpringBeanUtils.getBean("securityCheckers", List.class);
            if (!CollectionUtils.isEmpty(checkers)) {
                checkers.stream().forEach(checker -> steward.addSecurityChecker(checker));
            }
        }
        return bean;
    }
}
